﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Validity.Contexts;

namespace Validity.Test
{
  public class Account
  {
    public String Name { get; set; }
    public Int64 Number { get; set; }
    public DateTime Opened { get; set; }
    public DateTime? Closed { get; set; }
    public ModuleHandle Test { get; set; }
  }

  [TestClass]
  public class AccountValidatorTest
  {
    public class AccountValidator
      : ValidatorBase<Account>
    {
      public AccountValidator()
      {
        DefineRulesFor(acct => acct.Name)
          .IsNotWhiteSpace()
          .HasMaximumLengthOf(30)
          .IsNotEqualTo("Reserved").WhenUsingComparer(StringComparer.OrdinalIgnoreCase);
        DefineRulesFor(acct => acct.Number)
          .IsGreaterThanOrEqualTo(1000)
          .IsLessThan(10000);
        DefineRulesFor(acct => acct.Opened)
          .IsLessThanOrEqualTo(() => DateTime.Today)
          .IsGreaterThanOrEqualTo(acct => acct.Closed.Value).If(accnt => accnt.Closed.HasValue).ReplacingMessageWith("Some Custom Message");
        DefineRulesFor(acct => acct.Closed)
          .IsGreaterThanOrEqualTo(acct => acct.Opened).If(acct => acct.Closed.HasValue);
      }
    }

    [TestMethod]
    public void TestAccountValidator()
    {
      var validator = new AccountValidator();
      var account = new Account();

      IList<ValidationResult> result = validator.Validate(account).ToList();
    }
  }

  public class Customer
  {
    public String Name { get; set; }
    public String Number { get; set; }
    public IList<Account> Accounts { get; set; }
  }

  [TestClass]
  public class CustomerValidatorTest
  {
    public class CustomerValidator
      : ValidatorBase<Customer>
    {
      public CustomerValidator()
      {
        DefineRulesFor(cust => cust.Name)
          .IsNotWhiteSpace()
          .HasMaximumLengthOf(30);
        DefineRulesFor(cust => cust.Number)
          .IsNotWhiteSpace()
          .MatchesPattern(@"BN-\d\d\d\d\d").ReplacingMessageWith("Must match the pattern 'BN-#####'");
        DefineRulesFor(cust => cust.Accounts)
          .MustHave(cust => cust.Accounts != null && cust.Accounts.Count > 0).ReplacingMessageWith("Must have at least 1 account");
      }
    }

    [TestMethod]
    public void TestAccountValidator()
    {
      var validator = new CustomerValidator();
      var customer = new Customer();

      IList<ValidationResult> result = validator.Validate(customer).ToList();
    }
  }

  public static class ExactlyConstraintExtension
  {
    public static IValidationContext<TObject, String> IsExactly<TObject>(this IValidationContext<TObject, String> context, Int32 length)
    {
      return context.MustHave((obj, val) => (val ?? String.Empty).Length == length);
    }
  }
}
